using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Windows.Forms;
using FileSynchronizer.DataAccess;
using FileSynchronizer.Forms;
using FileSynchronizer.Objects;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using mylibrary;


namespace FileSynchronizer
{
    public partial class Form_Main : Form
    {
        #region Private variables
        //---------------------------------------------------------------------------------------------------------------------------------------
        
        private LogEntry log = new LogEntry();
        private string ApplicationTitle; 
        private Cursor OldCursor;
        private bool InitialPass;
        private bool TimerStarted;

        private IQueryable<FolderPair> myFolderPairs;
        private SyncDatabaseHelper mySyncDatabaseHelper;

        private ProgramContext myProgramContext;
        //---------------------------------------------------------------------------------------------------------------------------------------
        #endregion

        #region Constructors
        //---------------------------------------------------------------------------------------------------------------------------------------
        public Form_Main()
        {
            InitializeComponent();

            InitializeApplication();

            if (myProgramContext.Settings.RunMinimized)
            {
                InitialPass = true;
                ShowInTaskbar = false;
                WindowState = FormWindowState.Minimized;
            }
            else
            {
                InitialPass = false;
                notifyIcon1.Visible = false;
                ShowInTaskbar = true;
                WindowState = FormWindowState.Normal;
            }
        }

        //---------------------------------------------------------------------------------------------------------------------------------------
        // Windows Form Pre Processing
        //---------------------------------------------------------------------------------------------------------------------------------------
        private void InitializeApplication()
        {
            try
            {             
                // set Form Title
                ApplicationTitle = ApplicationAttributes.AssemblyProduct;
                this.Text = ApplicationTitle;
                notifyIcon1.Text = ApplicationTitle;

                log.EventId = 301;
                log.Categories.Add("Application Event");
                log.Severity = TraceEventType.Information;
                log.Priority = 5;
                log.Title = ApplicationTitle;
                log.Message = "Application Started";
                Logger.Write(log);

                myProgramContext = new ProgramContext();
                myProgramContext.LoadSettings();

                mySyncDatabaseHelper = new SyncDatabaseHelper();

                LoadFolderPairs();
                FolderPairDataGridView.Enabled = false;

                UpdateUserInterface();


                Program.TheSplashForm.Close();
            }
            catch (Exception ex)
            {
                FormHelperClass.ProcessUnhandledException(ex, ApplicationTitle);
            }
        }
        //---------------------------------------------------------------------------------------------------------------------------------------
        #endregion

        #region Internal Methods
        //---------------------------------------------------------------------------------------------------------------------------------------
        // Load Data from Database
        //---------------------------------------------------------------------------------------------------------------------------------------
        private void LoadFolderPairs()
        {
            try
            {
                myFolderPairs = mySyncDatabaseHelper.AllFolderPairs();
                folderPairBindingSource.DataSource = myFolderPairs;
                UpdateUserInterface();
            }
            catch (Exception ex)
            {
                FormHelperClass.ProcessUnhandledException(ex, ApplicationTitle);
            }
        }

        //---------------------------------------------------------------------------------------------------------------------------------------
        // Update the Userinterface, based on State
        //---------------------------------------------------------------------------------------------------------------------------------------
        private void UpdateUserInterface()
        {
            switch (myProgramContext.CurrentState)
            {
                case State.Initializing:
                    menuStrip1.Enabled = false;
                    button_ShowLog.Enabled = false;
                    button_SynchronizePair.Enabled = false;
                    button_SynchronizeAll.Enabled = false;
                    removeFolderPairToolStripMenuItem.Enabled = false;
                    SynchronizePairtoolStripMenuItem.Enabled = false;
                    showLogToolStripMenuItem.Enabled = false;
                    TimerStarted = false;
                    notifyIcon1.Visible = false;
                    break;

                case State.AutoSync:
                    toolStripStatusLabel1.Text = "Auto-Processing Folderpair";
                    break;

                case State.RunMinimized:
                    notifyIcon1.ShowBalloonTip(1, ApplicationTitle, "Done Autoprocessing", ToolTipIcon.Info);
                    if (myProgramContext.Settings.AutoTerminateApplication)
                    {
                        timer1.Interval = myProgramContext.Settings.TerminationWaitTime * 1000;
                        TimerStarted = true;
                        timer1.Start();
                    }
                    break;

                case State.Idle:
                    if (myFolderPairs.Count() > 0)
                    {
                        button_SynchronizeAll.Enabled = true;
                    }
                    else
                    {
                        button_SynchronizeAll.Enabled = false;
                    }
                    if (FolderPairDataGridView.SelectedRows.Count > 0)
                    {
                        SynchronizePairtoolStripMenuItem.Enabled = true;
                        removeFolderPairToolStripMenuItem.Enabled = true;
                        showLogToolStripMenuItem.Enabled = true;
                        button_ShowLog.Enabled = true;
                        button_SynchronizePair.Enabled = true;
                    }
                    else
                    {
                        SynchronizePairtoolStripMenuItem.Enabled = false;
                        removeFolderPairToolStripMenuItem.Enabled = false;
                        showLogToolStripMenuItem.Enabled = false;
                        button_ShowLog.Enabled = false;
                        button_SynchronizePair.Enabled = false;
                    }

                    FolderPairDataGridView.Enabled = true;
                    menuStrip1.Enabled = true;
                    
                    break;

            }
        }

        //---------------------------------------------------------------------------------------------------------------------------------------
        // Delete a folderpair and it's logs
        //---------------------------------------------------------------------------------------------------------------------------------------
        private bool DeleteFolderPair(FolderPair TheFolderPair)
        {
            bool OperationResult = true;

            try
            {
                OperationResult = myProgramContext.DeleteFolderPair(TheFolderPair, mySyncDatabaseHelper);
                
                // remove from lists
                LoadFolderPairs();
            }
            catch (Exception ex)
            {
                FormHelperClass.ProcessUnhandledException(ex, ApplicationTitle);
                OperationResult = false;
            }


            return OperationResult;
        }
        //---------------------------------------------------------------------------------------------------------------------------------------
        #endregion

        #region Synchronization of all FolderPairs
        //---------------------------------------------------------------------------------------------------------------------------------------
        // Callback Function which is called whenever the synchronization of ALL folderpairs is complete
        //---------------------------------------------------------------------------------------------------------------------------------------
        private void SyncFolderPairListCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            toolStripStatusLabel1.Text = "Done Autoprocessing";
            UpdateUserInterface();
            this.Cursor = OldCursor;
        }
        //---------------------------------------------------------------------------------------------------------------------------------------
        #endregion

        #region Event Handlers
        //---------------------------------------------------------------------------------------------------------------------------------------
        // Called when the User clicks "New Folderpair" in the menu
        //---------------------------------------------------------------------------------------------------------------------------------------
        private void OnNewFolderPairClick(object sender, EventArgs e)
        {
            FolderPair NewFolderPair;
            string TheSource = "";
            string TheDestination = "";
            bool AutoSynchronizeSetting = false;

            try
            {
                Form_NewFolderPair frm_NewFolderPair = new Form_NewFolderPair();
                if (frm_NewFolderPair.ShowDialog() == DialogResult.OK)
                {
                    if (myProgramContext.Settings.UseURLforMappedDrive)
                    {
                        TheSource = NetworkDriveHelper.ReplaceDriveLetterWithURL(frm_NewFolderPair.LeftFolder);
                        TheDestination = NetworkDriveHelper.ReplaceDriveLetterWithURL(frm_NewFolderPair.RightFolder);
                    }
                    else
                    {
                        TheSource = frm_NewFolderPair.LeftFolder;
                        TheDestination = frm_NewFolderPair.RightFolder;
                    }
                    AutoSynchronizeSetting = frm_NewFolderPair.AutoSynchronize;

                    if (SyncFolderPairHelper.IsValidFolderPair(myFolderPairs, TheSource, TheDestination))
                    {
                        NewFolderPair = mySyncDatabaseHelper.NewFolderPair(TheSource, TheDestination, AutoSynchronizeSetting);

                        LoadFolderPairs();
                    }                    
                    else
                    {
                        //show message
                        MessageBox.Show("New Folderpair is part of existing pair", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    }
                    frm_NewFolderPair = null;
                    FolderPairDataGridView.Focus();
                }
            }
            catch (Exception ex)
            {
                FormHelperClass.ProcessUnhandledException(ex, ApplicationTitle);
            }
        }

        //---------------------------------------------------------------------------------------------------------------------------------------
        // Called when the User clicks "Remove Folderpair" in the menu
        //---------------------------------------------------------------------------------------------------------------------------------------
        private void OnRemoveFolderPairClick(object sender, EventArgs e)
        {
            FolderPair myFolderPair;

            try
            {
                myFolderPair = (FolderPair)FolderPairDataGridView.CurrentRow.DataBoundItem;
                if (myFolderPair != null)
                {
                    if (MessageBox.Show("Are you sure you want to remove this folderpair", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                    {
                        DeleteFolderPair(myFolderPair);

                        FolderPairDataGridView.Focus();
                    }
                }
            }
            catch (Exception ex)
            {
                FormHelperClass.ProcessUnhandledException(ex, ApplicationTitle);
            }
        }

        //---------------------------------------------------------------------------------------------------------------------------------------
        // Called when the User selects another item in the listview
        //---------------------------------------------------------------------------------------------------------------------------------------
        private void OnFolderPairGridViewSelectionChanged(object sender, EventArgs e)
        {
            try
            {
                if (myProgramContext.CurrentState == State.Idle)
                {
                    if (FolderPairDataGridView.SelectedRows.Count > 0)
                    {
                        SynchronizePairtoolStripMenuItem.Enabled = true;
                        removeFolderPairToolStripMenuItem.Enabled = true;
                        showLogToolStripMenuItem.Enabled = true;
                        button_ShowLog.Enabled = true;
                        button_SynchronizePair.Enabled = true;
                    }
                    else
                    {
                        SynchronizePairtoolStripMenuItem.Enabled = false;
                        removeFolderPairToolStripMenuItem.Enabled = false;
                        showLogToolStripMenuItem.Enabled = false;
                        button_ShowLog.Enabled = false;
                        button_SynchronizePair.Enabled = false;
                    }
                }
            }
            catch (Exception ex)
            {
                FormHelperClass.ProcessUnhandledException(ex, ApplicationTitle);
            }
        }

        //---------------------------------------------------------------------------------------------------------------------------------------
        // Called when the User clicks the "Synchronize Folderpair" button
        //---------------------------------------------------------------------------------------------------------------------------------------
        private void OnSynchronizePairClick(object sender, EventArgs e)
        {
            FolderPair myFolderPair;

            try
            {
                myFolderPair = (FolderPair)FolderPairDataGridView.CurrentRow.DataBoundItem;
                if (myFolderPair != null)
                {
                    myProgramContext.SynchronizeFolderPair(myFolderPair, mySyncDatabaseHelper);

                    FolderPairDataGridView.Focus();
                }
                UpdateUserInterface();
            }
            catch (Exception ex)
            {
                FormHelperClass.ProcessUnhandledException(ex, ApplicationTitle);
            }
        }

        //---------------------------------------------------------------------------------------------------------------------------------------
        // Called when form is resized
        //---------------------------------------------------------------------------------------------------------------------------------------
        private void OnResize(object sender, EventArgs e)
        {
            if (WindowState == FormWindowState.Minimized)
            {
                ShowInTaskbar = false;
                notifyIcon1.Visible = true;
                Hide();
                if (InitialPass == false)
                {
                    notifyIcon1.ShowBalloonTip(500, ApplicationTitle, "The Application is still running, double-click the icon to show it", ToolTipIcon.Info);
                }
            }

            if (WindowState == FormWindowState.Normal)
            {
                ShowInTaskbar = true;
                InitialPass = false;
                if (TimerStarted)
                {
                    timer1.Stop();
                }
            }
        }

        //---------------------------------------------------------------------------------------------------------------------------------------
        // Called when the notifyIcon is double-clicked
        //---------------------------------------------------------------------------------------------------------------------------------------
        private void OnNotifyIconDoubleClick(object sender, EventArgs e)
        {
            Show();
            notifyIcon1.Visible = false;
            WindowState = FormWindowState.Normal;
            if (myProgramContext.CurrentState != State.AutoSync)
            {
                myProgramContext.RunNotMinimized();

                UpdateUserInterface();
            }
            // Activate the form.
            this.Activate();
            this.Focus();

        }

        //---------------------------------------------------------------------------------------------------------------------------------------
        // Called when the Synchronize All Button is clicked
        //---------------------------------------------------------------------------------------------------------------------------------------
        private void OnButtonSynchronizeAll_Click(object sender, EventArgs e)
        {
            try
            {
                if (myFolderPairs != null)
                {

                    myProgramContext.SynchronizeAllFolderPairs(myFolderPairs);
                    FolderPairDataGridView.Focus();
                }
                UpdateUserInterface();
            }
            catch (Exception ex)
            {
                FormHelperClass.ProcessUnhandledException(ex, ApplicationTitle);
            }
        }

        //---------------------------------------------------------------------------------------------------------------------------------------
        // Called when the Form is first shown
        //---------------------------------------------------------------------------------------------------------------------------------------
        private void OnShown(object sender, EventArgs e)
        {

            OldCursor = this.Cursor;
            this.Cursor = Cursors.WaitCursor;
            
            myProgramContext.ProcessStartup(myFolderPairs, SyncFolderPairListCompleted);
        }

        //---------------------------------------------------------------------------------------------------------------------------------------
        // Called when the Form is Closed
        //---------------------------------------------------------------------------------------------------------------------------------------
        private void OnClosed(object sender, FormClosedEventArgs e)
        {
            log.Title = ApplicationTitle;
            log.Message = "Application Closed";
            Logger.Write(log);

            myProgramContext.SaveSettings();
        }

        //---------------------------------------------------------------------------------------------------------------------------------------
        // Called when the User clicks "Exit" in the menu
        //---------------------------------------------------------------------------------------------------------------------------------------
        private void OnExitClick(object sender, EventArgs e)
        {
            this.Close();
        }

        //---------------------------------------------------------------------------------------------------------------------------------------
        // Called when the User clicks "Settings" in the menu
        //---------------------------------------------------------------------------------------------------------------------------------------
        private void OnSettingsClick(object sender, EventArgs e)
        {
            try
            {
                FileSynchronizerSettings mySettings = myProgramContext.Settings;

                Form_Settings frm_Settings = new Form_Settings();
                frm_Settings.RunMinimized = mySettings.RunMinimized;
                frm_Settings.SyncAtStartup = mySettings.SyncAtStartup;
                frm_Settings.UseURLforMappedDrive = mySettings.UseURLforMappedDrive;
                frm_Settings.AutoTerminateApplication = mySettings.AutoTerminateApplication;
                frm_Settings.TerminationWaitTime = mySettings.TerminationWaitTime;
                frm_Settings.RunWhenUserLogsOn = mySettings.RunWhenUserLogsOn;
                frm_Settings.DisableFolderWarning = mySettings.DisableFolderWarning;
                frm_Settings.EnableEnterpriseFeatures = mySettings.EnableEnterpriseFeatures;
                frm_Settings.LatencyEnabled = mySettings.LatencyEnabled;
                frm_Settings.LatencyTimeout = mySettings.LatencyTimeout;

                if(frm_Settings.ShowDialog() == DialogResult.OK)
                {
                    mySettings.RunMinimized = frm_Settings.RunMinimized;
                    mySettings.SyncAtStartup = frm_Settings.SyncAtStartup;
                    mySettings.UseURLforMappedDrive = frm_Settings.UseURLforMappedDrive;
                    mySettings.AutoTerminateApplication = frm_Settings.AutoTerminateApplication;
                    mySettings.TerminationWaitTime = frm_Settings.TerminationWaitTime;
                    mySettings.RunWhenUserLogsOn = frm_Settings.RunWhenUserLogsOn;
                    mySettings.DisableFolderWarning = frm_Settings.DisableFolderWarning;
                    mySettings.EnableEnterpriseFeatures = frm_Settings.EnableEnterpriseFeatures;
                    mySettings.LatencyEnabled = frm_Settings.LatencyEnabled;
                    mySettings.LatencyTimeout = frm_Settings.LatencyTimeout;

                    if (frm_Settings.RunWhenUserLogsOn)
                    {
                        if (!ApplicationAttributes.IsAutoStartEnabled(ApplicationTitle))
                        {
                            ApplicationAttributes.EnableAutoStart(ApplicationTitle);
                        }
                    }
                    else
                    {
                        if (ApplicationAttributes.IsAutoStartEnabled(ApplicationTitle))
                        {
                            ApplicationAttributes.DisableAutoStart(ApplicationTitle);
                        }
                    }
                    myProgramContext.SaveSettings();
                }
                frm_Settings = null;
            }
            catch (Exception ex)
            {
                FormHelperClass.ProcessUnhandledException(ex, ApplicationTitle);
            }
        }

        //---------------------------------------------------------------------------------------------------------------------------------------
        // Called when the Timed Event has been triggered to terminate the applicatiuon
        //---------------------------------------------------------------------------------------------------------------------------------------
        private void OnTimer(object sender, EventArgs e)
        {
            this.Close();
        }

        //---------------------------------------------------------------------------------------------------------------------------------------
        // Called when the User clicks "About FileSynchronizer" in the menu
        //---------------------------------------------------------------------------------------------------------------------------------------
        private void OnAboutClick(object sender, EventArgs e)
        {
            try
            {
                Form_About myAboutBox = new Form_About();
                myAboutBox.ShowDialog();
                myAboutBox = null;
            }
            catch (Exception ex)
            {
                FormHelperClass.ProcessUnhandledException(ex, ApplicationTitle);
            }
        }

        //---------------------------------------------------------------------------------------------------------------------------------------
        // Called when the User clicks "Show Synchronization Log" in the menu
        //---------------------------------------------------------------------------------------------------------------------------------------
        private void OnShowLogClick(object sender, EventArgs e)
        {
            FolderPair myFolderPair;
            Form_ShowLog frm_ShowLog;

            try
            {
                myFolderPair = (FolderPair)FolderPairDataGridView.CurrentRow.DataBoundItem;
                if (myFolderPair != null)
                {
                    frm_ShowLog = new Form_ShowLog(myFolderPair);
                    frm_ShowLog.ShowDialog();
                    frm_ShowLog = null;

                    FolderPairDataGridView.Focus();
                }
            }
            catch (Exception ex)
            {
                FormHelperClass.ProcessUnhandledException(ex, ApplicationTitle);
            }

        }
        //---------------------------------------------------------------------------------------------------------------------------------------
        #endregion
    }

}
